
#include <BTcpSocket>
#include <BTcpServer>
#include "member_BSocket.h"
#include "member_BTcpServer.h"

using namespace BWE;

#define member					(*(member_BTcpServer*)_ptr)
#define member_allocate()		_ptr = new member_BTcpServer(this)
#define member_release()		delete (member_BTcpServer*)_ptr

#ifdef linux
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>

BTcpServer::BTcpServer()
{
	member_allocate();
	socket_member(this)->create(AF_INET, SOCK_STREAM, 0);
	socket_member(this)->setnonblock();
}
BTcpServer::~BTcpServer()
{
	member_release();
}

BTcpServer::Type BTcpServer::type() const
{
	return TcpServer;
}

bool BTcpServer::bind(const BString& address, int port)
{
	sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr(address.cstr());

	int ret = ::bind(socket_member(this)->sock, (sockaddr*)&addr, sizeof(addr));
	if (ret == -1)
	{
		perror("bind");
		return false;
	}
	socket_member(this)->address = address;
	socket_member(this)->port = port;
	return true;
}

bool BTcpServer::listen(int maximum)
{
	int ret = ::listen(socket_member(this)->sock, maximum);
	if (ret == -1)
	{
		perror("listen");
		return false;
	}
	socket_member(this)->state = State_Listening;
	this->emit(Signal_StateChanged, State_Listening);
	return true;
}

#endif

#ifdef _WIN32

BTcpServer::BTcpServer()
{
	member_allocate();
}
BTcpServer::~BTcpServer()
{
	member_release();
}

BTcpServer::Type BTcpServer::type() const
{
	return TcpServer;
}

bool BTcpServer::bind(const BString& address, int port)
{
	sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	InetPtonA(AF_INET, address.cstr(), &(addr.sin_addr.S_un.S_addr));

	if (socket_member(this)->sock == 0)
		socket_member(this)->create(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	if (socket_member(this)->sock == 0)
		return false;

	int ret = ::bind(socket_member(this)->sock, (sockaddr*)&addr, sizeof(addr));
	if (ret == SOCKET_ERROR)
	{
		socket_member(this)->checkError();
		perror(socket_member(this)->errorStr);
		return false;
	}
	socket_member(this)->address = address;
	socket_member(this)->port = port;
	return true;
}
bool BTcpServer::listen(int maximum)
{
	if (socket_member(this)->sock == 0)
		socket_member(this)->create(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	if (socket_member(this)->sock == 0)
		return false;

	int ret = ::listen(socket_member(this)->sock, maximum);
	if (ret == SOCKET_ERROR)
	{
		int errorCode = WSAGetLastError();
		perror("bind");
		return false;
	}
	socket_member(this)->state = State_Listening;
	this->emit(Signal_StateChanged, State_Listening);
	return true;
}

#endif

int BTcpServer::socketCount() const
{
	return member.tcpSockets.size();
}
BTcpSocket* BTcpServer::socket(int index)
{
	return member.tcpSockets(index);
}
const BTcpSocket* BTcpServer::socket(int index) const
{
	return member.tcpSockets(index);
}


